package org.mspring.mlog.service.impl;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.ClassUtils;
import org.mspring.mlog.entity.Job;
import org.mspring.mlog.schedule.SchedulerService;
import org.mspring.mlog.service.JobService;
import org.mspring.platform.dao.hibernate.GenericDao;
import org.mspring.platform.exception.BusinessException;
import org.mspring.platform.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 
 * @author Gao Youbo
 * @since 2013-06-18 16:34:42
 */
@Service
@Transactional
@SuppressWarnings("rawtypes")
public class JobServiceImpl extends GenericDao<Job, java.lang.Long> implements JobService {

    @Autowired
    private SchedulerService schedulerService;

    @Override
    public void setEnabled(boolean enabled, Long... id) {
        // TODO Auto-generated method stub
        if (id != null) {
            for (Long i : id) {
                executeUpdate("update Job job set job.enabled = ? where job.id = ?", new Object[] { enabled, i });
            }
        }
    }

    @Override
    public void setExpressions(Long[] ids, String[] expressions) {
        // TODO Auto-generated method stub
        if (ids == null || expressions == null || ids.length == 0 || expressions.length == 0) {
            log.error("ids or expressions is empty", new BusinessException("ids or expressions is empty"));
        }
        if (ids.length != expressions.length) {
            log.error("ids.length != expressions.length", new BusinessException("ids.length != expressions.length"));
        }

        for (int i = 0; i < ids.length; i++) {
            Long id = ids[i];
            String expression = expressions[i];
            if (id == null || StringUtils.isBlank(expression)) {
                log.warn("id or expression is null");
                continue;
            }
            executeUpdate("update Job job set job.expression = ? where job.id = ?", new Object[] { expression, id });
        }
    }

    @Override
    public void setExecTypes(Long[] ids, String[] execTypes) {
        // TODO Auto-generated method stub
        if (ids == null || execTypes == null || ids.length == 0 || execTypes.length == 0) {
            log.error("ids or execTypes is empty", new BusinessException("ids or execTypes is empty"));
        }
        if (ids.length != execTypes.length) {
            log.error("ids.length != execTypes.length", new BusinessException("ids.length != execTypes.length"));
        }

        for (int i = 0; i < ids.length; i++) {
            Long id = ids[i];
            String execType = execTypes[i];
            if (id == null || StringUtils.isBlank(execType)) {
                log.warn("id or expression is null");
                continue;
            }
            executeUpdate("update Job job set job.execType = ? where job.id = ?", new Object[] { execType, id });
        }
    }

    @Override
    public void reloadJobServer(Long id) {
        // TODO Auto-generated method stub
        Job job = get(id);
        reloadJobServer(job);
    }

    @Override
    public void reloadJobServer(Job job) {
        // TODO Auto-generated method stub
        String className = job.getJobClass();
        if (StringUtils.isBlank(className)) {
            log.error("can't register job server, jobClass is null.");
            throw new BusinessException("can't register job server, jobClass is null.");
        }
        Class clazz = null;
        try {
            clazz = ClassUtils.getClass(className);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            log.error(String.format("can't register job server, class not found. [id=%s, className=%s]", job.getId(), className));
            throw new BusinessException(String.format("can't register job server, class not found. [id=%s, className=%s]", job.getId(), className));
        }

        String execType = job.getExecType();
        if (StringUtils.isBlank(execType))
            execType = Job.ExecType.SIMPLE;
        try {
            if (execType.equalsIgnoreCase(Job.ExecType.CRON)) {
                schedulerService.schedule(job.getId().toString(), clazz, job.getExpression());
            } else {
                Long repeatInterval = new Long(job.getExpression());
                schedulerService.schedule(job.getId().toString(), clazz, repeatInterval);
            }
        } catch (Exception e) {
            // TODO: handle exception
            log.error(String.format("can't register job server. [id=%s, className=%s, execType=%s, expression=%s]", job.getId(), className, execType, job.getExpression()), e);
        }
    }

    @Override
    public void loadJobServer() {
        // TODO Auto-generated method stub
        log.info("init JobService...");
        schedulerService.clearJobs();
        List<Job> enabledJobs = list("select job from Job job where job.enabled = ?", true);
        for (Job job : enabledJobs) {
            try {
                reloadJobServer(job);
                log.info(String.format("Job Server load success. name = [id=%s, className=%s, execType=%s, expression=%s]", job.getId(), job.getClass(), job.getExecType(), job.getExpression()));
            } catch (Exception e) {
                // TODO: handle exception
                log.error(e.getMessage());
                continue;
            }
        }
    }

    @Override
    public void triggerJob(Long id) {
        // TODO Auto-generated method stub
        if (id == null) {
            return;
        }
        schedulerService.triggerJob(id.toString());
    }

    @Override
    public void updateLastExec(Long id, Date date) {
        // TODO Auto-generated method stub
        executeUpdate("update Job job set job.lastExec = ? where job.id = ?", date, id);
    }

}
